package com.dhruvtaara.beta.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import com.dhruvtaara.beta.model.entities.OnlineExam;
import com.dhruvtaara.beta.model.persistance.Datastore;
import com.dhruvtaara.beta.model.viewmodel.ExamAnswer;
import com.dhruvtaara.beta.model.viewmodel.ExamQuestion;
import com.dhruvtaara.beta.model.viewmodel.ExamStartInfo;
import com.dhruvtaara.beta.toolset.DateUtil;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;

public class OnlineExamAction {

	private long examId;

	/**
	 * 
	 * @param userId
	 * @return
	 */
	public List<ExamQuestion> getQuestions(long userId) {
		DatastoreService datastore = Datastore.get();

		Entity examEntity = new Entity("OnlineExam");
		examEntity.setProperty("userId", userId);
		datastore.put(examEntity);

		this.setExamId(examEntity.getKey().getId());

		List<ExamQuestion> questions = this.getRandomQuestions(5,
				this.getExamId());

		return questions;
	}

	/**
	 * Send one question at a time to the browser
	 * 
	 * @param ordinal
	 * @param questions
	 *            Save the set in session
	 * @return
	 */
	public ExamQuestion getQuestion(int ordinal, List<ExamQuestion> questions) {
		return questions.get(ordinal);
	}

	/**
	 * 
	 * @param question
	 * @param answer
	 */
	public void setAnswer(ExamQuestion question, ExamAnswer answer) {
		DatastoreService datastore = Datastore.get();

		Entity examDataEntity = new Entity("OnlineExamResponse");
		examDataEntity.setProperty("examId", question.getExamId());
		examDataEntity.setProperty("questionId", question.getId());
		examDataEntity.setProperty("userAnswer", answer.getAnswers());
		datastore.put(examDataEntity);
	}

	/**
	 * 
	 * @param count
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<ExamQuestion> getRandomQuestions(int count, long examId) {
		DatastoreService datastore = Datastore.get();

		List<ExamQuestion> examQuestions = new ArrayList<ExamQuestion>();

		Query query = new Query("Question");
		Iterable<Entity> questions = datastore.prepare(query).asIterable();

		for (Entity q : questions) {
			ExamQuestion question = new ExamQuestion();
			question.setId(q.getKey().getId());
			question.setQuestion(q.getProperty("text").toString());
			question.setExamId(examId);
			List<String> choices = (List<String>) q.getProperty("choices");
			question.setChoices(choices);
			examQuestions.add(question);
		}

		return examQuestions;
	}

	/**
	 * 
	 * @param userAborted
	 * @param examId
	 * @param userId
	 */
	public void abortExam(boolean userAborted, long examId, long userId) {
		DatastoreService datastore = Datastore.get();

		Query query = new Query("OnlineExam");
		query.addFilter(Entity.KEY_RESERVED_PROPERTY, FilterOperator.EQUAL,
				OnlineExam.getKey(examId));
		Entity examEntity = datastore.prepare(query).asSingleEntity();

		examEntity.setProperty("isExamAborted", true);
		examEntity.setProperty("userAborted", userAborted);
		examEntity.setProperty("timeAborted", DateUtil.getCurrentTime());

		datastore.put(examEntity);
	}

	/**
	 * 
	 * @param userId
	 * @param scheduledAt
	 */
	public void scheduleExam(long userId, Date scheduledAt) {

	}

	/**
	 * 
	 * @param userId
	 * @return
	 */
	public ExamStartInfo canStartExam(long userId) {

		ExamStartInfo startInfo = new ExamStartInfo();
		DatastoreService datastore = Datastore.get();
		Query query = new Query("OnlineExam");
		query.addFilter("userId", FilterOperator.EQUAL, userId);
		Iterator<Entity> examEntities = datastore.prepare(query).asIterator();

		Entity exam = null;
		while (examEntities.hasNext()) {
			exam = examEntities.next();
		}
		if (exam == null) {
			startInfo.setStartCode(0);// start the exam
			startInfo.setMessage("Start the exam now");
		} else {
			Object isExamAborted = exam.getProperty("isExamAborted");
			Object scheduledAt = exam.getProperty("scheduledAt");

			if (isExamAborted != null && scheduledAt == null) {
				startInfo.setStartCode(1);// suggest user to schedule the exam
				startInfo.setMessage("Your previous exam was aborted, please schedule an exam");
			}
			if (isExamAborted != null && scheduledAt != null) {
				startInfo.setStartCode(2);// suggest user the time to start the
											// exam				
				startInfo.setFormattedDate(DateUtil
						.getDefaultFormattedDate((Long) scheduledAt));
				startInfo.setMessage("Your exam has been scheduled to begin at " + startInfo.getFormattedDate());
				if (DateUtil.isTimeInRange((Long) scheduledAt, 30)) {
					startInfo.setStartCode(4);// exam can be taken now
					startInfo.setMessage("Start the exam now");
				}
			}
			if (isExamAborted == null) {
				startInfo.setStartCode(3);// exam has already been taken;
											// suggest to
											// schedule another if required
				startInfo.setMessage("You have already taken this exam, do you like to appear again?");
			}
		}
		return startInfo;
	}

	/**
	 * 
	 * @param examId
	 */
	public void setExamId(long examId) {
		this.examId = examId;
	}

	public long getExamId() {
		return examId;
	}

	/**
	 * 
	 * @param userId
	 * @return
	 */
	public ExamStartInfo checkExamAvailable(int userId) {
		ExamStartInfo startInfo = this.canStartExam(userId);
		return startInfo;
	}

	/**
	 * 
	 * @param ordinal
	 * @param examQuestions
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<ExamQuestion> getNextQuestion(int ordinal, Object examQuestions) {

		List<ExamQuestion> questions = new ArrayList<ExamQuestion>();
		questions.add(this.getQuestion(ordinal,
				(List<ExamQuestion>) examQuestions));

		return questions;
	}

	/**
	 * 
	 * @param questionId
	 * @param examId
	 * @param responses
	 */
	public void setUserAnswer(int questionId, long examId, String responses) {
		if (responses != null && responses.length() > 0) {
			ExamQuestion question = new ExamQuestion();
			question.setId(questionId);
			question.setExamId(examId);

			ExamAnswer answer = new ExamAnswer();
			answer.setQuestionId(questionId);
			String[] parts = responses.split(",");
			List<Integer> userAnswers = new ArrayList<Integer>();
			for (String part : parts) {
				userAnswers.add(Integer.parseInt(part));
			}
			answer.setAnswers(userAnswers);

			this.setAnswer(question, answer);
		}

	}
}